package l2s.gameserver.scripts.custom;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.Socket;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.concurrent.ScheduledFuture;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import l2s.commons.configuration.Config;
import l2s.commons.db.DatabaseFactory;
import l2s.commons.util.Rnd;
import l2s.gameserver.ThreadPoolManager;
import l2s.gameserver.model.actor.instance.L2PcInstance;

public class L2TopDeamon implements Runnable
{
	protected static final Logger _log = LoggerFactory.getLogger("L2TopDeamon");
	
	public static L2TopDeamon getInstance()
	{
		return SingletonHolder._instance;
	}
	
	protected ScheduledFuture<?> _task;
	private Timestamp _lastVote;
	private boolean _firstRun = false;
	
	protected class Terminator extends Thread
	{
		@Override
		public void run()
		{
			_log.info("L2TopDeamon: stopped");
			try
			{
				if (L2TopDeamon.getInstance()._task != null)
				{
					L2TopDeamon.getInstance()._task.cancel(true);
				}
			}
			catch (Exception e)
			{
				
			}
		}
	}
	
	protected L2TopDeamon()
	{
		_lastVote = null;
		if (Config.L2TOPDEMON_ENABLED)
		{
			_log.info("Service: Loading L2Top Parser...");
			try (Connection con = DatabaseFactory.getConnection())
			{
				PreparedStatement stm = con.prepareStatement("select max(votedate) from l2top_votes");
				ResultSet r = stm.executeQuery();
				if (r.next())
				{
					_lastVote = r.getTimestamp(1);
				}
				if (_lastVote == null)
				{
					_firstRun = true;
					_lastVote = new Timestamp(0);
				}
				r.close();
				stm.close();
				
				_task = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(this, 60000, Config.L2TOPDEMON_POLLINTERVAL * 60000);
				Runtime.getRuntime().addShutdownHook(new Terminator());
				_log.info("L2TopDeamon: Started with poll interval " + Config.L2TOPDEMON_POLLINTERVAL + " minute(s)");
			}
			catch (SQLException e)
			{
				_log.info("L2TopDeamon: Error ThreadConnection to database: " + e.getMessage());
			}
		}
		else
		{
			_log.info("Service: L2Top Parser - Disabled.");
		}
	}
	
	private class VotesUpdate implements Runnable
	{
		private final Timestamp _votedate;
		private final String _charName;
		private final boolean _fr;
		
		public VotesUpdate(Timestamp votedate, String charName, boolean fr)
		{
			_votedate = votedate;
			_charName = charName;
			_fr = fr;
		}
		
		@Override
		public void run()
		{
			try (Connection con = DatabaseFactory.getConnection())
			{
				PreparedStatement stm = con.prepareStatement("insert into l2top_votes select ?,? from characters where not exists(select * from l2top_votes where votedate=? and charName =?) limit 1");
				stm.setTimestamp(1, _votedate);
				stm.setTimestamp(3, _votedate);
				stm.setString(2, _charName);
				stm.setString(4, _charName);
				boolean sendPrize = stm.executeUpdate() > 0;
				stm.close();
				if (_fr && Config.L2TOPDEMON_IGNOREFIRST)
				{
					sendPrize = false;
				}
				if (sendPrize)
				{
					L2PcInstance player = VoteUtils.loadPlayer(_charName);
					if (player != null)
					{
						int numItems = Config.L2TOPDEMON_MIN;
						if (Config.L2TOPDEMON_MAX > Config.L2TOPDEMON_MIN)
						{
							numItems += Rnd.get(Config.L2TOPDEMON_MAX - Config.L2TOPDEMON_MIN);
						}
						player.addItem("l2top", Config.L2TOPDEMON_ITEM, numItems, null, true);
						if (player.isOnline() && (Config.L2TOPDEMON_MESSAGE != null) && (Config.L2TOPDEMON_MESSAGE.length() > 0))
						{
							player.sendMessage(Config.L2TOPDEMON_MESSAGE);
						}
						player.store();
					}
				}
			}
			catch (SQLException e)
			{
				_log.info("Error insert into l2top_votes " + e);
			}
		}
	}
	
	private boolean checkVotes()
	{
		Socket s;
		try
		{
			_log.info("L2TopDeamon: Checking l2top.ru....");
			int nVotes = 0;
			s = new Socket("l2top.ru", 80);
			s.setSoTimeout(30000);
			String request = "GET " + Config.L2TOPDEMON_URL + " HTTP/1.1\r\n" + "User-Agent: http:\\" + Config.EXTERNAL_HOSTNAME + " server\r\n" + "Host: http:\\" + Config.EXTERNAL_HOSTNAME + " \r\n" + "Accept: */*\r\n" + "Connection: close\r\n" + "\r\n";
			s.getOutputStream().write(request.getBytes());
			BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream(), "Cp1251"));
			Timestamp last = _lastVote;
			for (String line = in.readLine(); line != null; line = in.readLine())
			{
				if (line.indexOf("\t") != -1)
				{
					Timestamp voteDate = Timestamp.valueOf(line.substring(0, line.indexOf("\t")).trim());
					if (voteDate.after(_lastVote))
					{
						if (voteDate.after(last))
						{
							last = voteDate;
						}
						String charName = line.substring(line.indexOf("\t") + 1).toLowerCase();
						if ((Config.L2TOPDEMON_PREFIX != null) && (Config.L2TOPDEMON_PREFIX.length() > 0))
						{
							if (charName.startsWith(Config.L2TOPDEMON_PREFIX))
							{
								charName = charName.substring(Config.L2TOPDEMON_PREFIX.length());
							}
							else
							{
								continue;
							}
						}
						ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate((new VotesUpdate(voteDate, charName, _firstRun)), 60000, 60000);
						nVotes++;
					}
				}
			}
			s.close();
			_lastVote = last;
			_log.info("L2TopDeamon: " + nVotes + " vote(s) parsed");
			return true;
		}
		catch (Exception e)
		{
			_log.info("L2TopDeamon: Error while reading data" + e);
		}
		return false;
	}
	
	@Override
	public void run()
	{
		checkVotes();
		_firstRun = false;
	}
	
	private static class SingletonHolder
	{
		protected static final L2TopDeamon _instance = new L2TopDeamon();
	}
	
	public static void onLoad()
	{
		L2TopDeamon.getInstance();
	}
}
